// To compile with MinGW:
//
//      gcc serial.c -lwinmm -o serial
//

#include <windows.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    bool close_port = false;

    // Declare variables and structures
    HANDLE hSerial;
    DCB dcbSerialParams = {0};
    COMMTIMEOUTS timeouts = {0};

    // Open the highest available serial port number
    fprintf(stderr, "Opening serial port...");
    hSerial = CreateFile(
        "\\\\.\\COM6", GENERIC_READ | GENERIC_WRITE, 0, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "Error\n");
        return 1;
    }
    else
        fprintf(stderr, "OK\n");

    // Set device parameters (115200 baud, 1 start bit,
    // 1 stop bit, no parity)
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (GetCommState(hSerial, &dcbSerialParams) == 0)
    {
        fprintf(stderr, "Error getting device state\n");
        CloseHandle(hSerial);
        return 1;
    }

    dcbSerialParams.BaudRate = CBR_115200;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (SetCommState(hSerial, &dcbSerialParams) == 0)
    {
        fprintf(stderr, "Error setting device parameters\n");
        CloseHandle(hSerial);
        return 1;
    }

    // Set COM port timeout settings
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (SetCommTimeouts(hSerial, &timeouts) == 0)
    {
        fprintf(stderr, "Error setting timeouts\n");
        CloseHandle(hSerial);
        return 1;
    }

    while (close_port == false)
    {
        // Ask for character to send
        char bytes_to_send[1];
        printf("Enter a command (a = attack, b = bow, c = cast, e = electric, f = fire, i = ice, m = magic missiles, ");
        printf("\n                 p = poison, 1 - 4 = player 1 - 4, 0 = clear, x = close serial port): ");
        scanf(" %c", &bytes_to_send[0]);
        if (bytes_to_send[0] == 'x')
        {
            close_port = true;
        }

        // Send specified text (remaining command line arguments)
        DWORD bytes_written, total_bytes_written = 0;
        fprintf(stderr, "Sending bytes...");
        if (!WriteFile(hSerial, bytes_to_send, 1, &bytes_written, NULL))
        {
            fprintf(stderr, "Error\n");
            CloseHandle(hSerial);
            return 1;
        }
        fprintf(stderr, "%d bytes written\n", bytes_written);
        if (bytes_to_send[0] == 'a')
        {
            PlaySound(TEXT("sword.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'b')
        {
            PlaySound(TEXT("bow.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'c')
        {
            PlaySound(TEXT("cast.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'e')
        {
            PlaySound(TEXT("electric.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'f')
        {
            PlaySound(TEXT("fire.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'i')
        {
            PlaySound(TEXT("ice.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'm')
        {
            PlaySound(TEXT("mm.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
        if (bytes_to_send[0] == 'p')
        {
            PlaySound(TEXT("poison.wav"), GetModuleHandle(NULL), SND_FILENAME);
        }
    }
    // Close serial port
    fprintf(stderr, "Closing serial port...");
    if (CloseHandle(hSerial) == 0)
    {
        fprintf(stderr, "Error\n");
        return 1;
    }
    fprintf(stderr, "OK\n");
    return 0;
}